///////////////////////////////////////////////////////////
///////////////// Have an itch? Scratch it! ///////////////
///////////////////////// SCRATCH /////////////////////////
/////////////////////  A MUD  Server   ////////////////////
///////////////////// By: Jared Devall ////////////////////
/////////////////////      Thanks:     ////////////////////
/////////////////////  DIKU/Merc/ROM   ////////////////////
///////////////////// Aetas/Deus Gang  ////////////////////
/////////////////////       Beej       ////////////////////
///////////////////////////////////////////////////////////
// Altered by CTonk ( ctonk@hotmail.com )

// socket.h

#ifndef __SOCKET_H_
#define __SOCKET_H_

#ifndef WIN32
	#include <sys/types.h>
	#include <sys/time.h>
#else
	#include <winsock.h>
#endif

#include <list>

#define MAX_BUFFER 4096
#define EWOULDBLOCK EAGAIN
#define BACKLOG 15


class Socket
{
	bool         _disconnected;
	bool         _gotInput;
	std::string  _input;  // The data that the user is sending
	std::string  _output; // The data that the user will recieve	
	std::string  _ipAddress;   // The IP of user.
	std::string  _host;  // The Long host. __@__
	int			 _sockfd; // This is the socket number!
	
	public:
				 Socket();
				 ~Socket();
	void         FlushOutput( void );
	void         FlushInput( void );
	void         SetInput( const std::string & );
	void         SetOutput( const std::string & );
	void		 SetGotInput( bool value );
	bool		 GotInput( void );
	std::string  GetInput( void );
	std::string  GetOutput( void );
	void         SetSocketIP( const std::string & );
	std::string  GetSocketIP( void );
	void         SetSocketHost( const std::string & );
	std::string  GetSocketHost( void );
	int			 GetDescriptor( void );
	void         SetDescriptor( int desc );
	void         Send( char * message, ... );
	void         Send( const std::string & );
	void         SetDisconnected( bool value );
	bool         IsDisconnected( void );
};

class SocketServer
{
	public:
		fd_set		_fd_read; 
		fd_set		_fd_exc;
		int			_sockfd;	 
		int			_defaultPort;
		bool		_newConnection;
		
		enum RecieveReturn
		{
			Complete, Incomplete, Disconnected
		};

		#ifdef WIN32
			void InitWinsock( void ); // Need to Initialize Winsock.
			void DeInitWinsock( void ); // Call this when you close the Program.
		#endif
		bool CreateSocket( void );
		bool ReuseAddress( void );
		bool BindSocket( int port );
		bool ListenSocket( void );	
		void ConceiveConnection( void );
		void ChaperoneConnections( void );	
		int  RecieveInput( Socket* socket );
		bool SendOutput( Socket* socket );
		void KillDisconnectedSockets( void );

		SocketServer();
		~SocketServer();
		static SocketServer& Instance();
		void KillSocket( Socket* socket );
		int  GetHostSocket( void );
		void SetHostSocket( int sockfd );
		void Start( void );
		void Start( int port );
		bool Monitor( );	
		std::list< Socket* > _socketList;	 // Connected sockets
};

// Our singleton instance
inline SocketServer& SocketServer::Instance()
{
	static SocketServer instance;
	return instance;
}

#endif